home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
cgazv5n5.arc
/
LZW2.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-23
|
7KB
|
179 lines
/*--- LZW2.C ----------------------------- Listing 3 ----
* Contents: This is the decompression portion of
* the LZW data compression program. It
* contains the following routines:
* decompression_routine
* read_compressed_file
* output_character
* code_not_present
* new_code
* next_symbol
* push_onto_stack
* pop_off_of_stack
* put_into_table
*
* Author: Dwayne Phillips
* Compiler: Microsoft C 6.0a, BC++ 2.0
* Note: Must link with at least an 8K stack
* Switches: DEBUG - if defined, debugging data is shown
* STATS - if defined, statistics are given
* Date: February 1991
* May be used freely if authorship is acknowledged
*-------------------------------------------------------*/
#include "lzw.h"
/*--------------------------------------------------------
* This is the main routine for the decompression process.
*------------------------------------------------------*/
void decompression_routine( table_item *string_table,
FILE *infile, FILE *outfile )
{
int k, last_k, already_entered;
code_type in_buffer[IB_LENGTH_D], w_code, last_code;
unsigned table_max;
unsigned in_counter, out_counter, codes_read;
unsigned char out_buffer[OB_LENGTH_D];
unsigned char w[100], w2[100];
unsigned i, j;
/* start up */
out_counter = 0;
table_max = initialize ( string_table );
codes_read = read_compressed_file ( in_buffer, infile );
/* process first code now */
SHOW( printf ( "\nIn: %d", in_buffer[0] ); )
k = last_k = string_table[in_buffer[0]].character;
output_char ( k, out_buffer, &out_counter, outfile );
create_string ( w, k );
w_code = last_code = k;
in_counter = 1;
already_entered = 0;
for (;;) {
for ( ; in_counter < codes_read; in_counter++ ) {
code_type ct;
SHOW( printf( "\nIn: %d", in_buffer[in_counter]); )
if ( in_buffer[in_counter] > table_max ) {
/* A code that we don't know yet. We must infer
what the compression routine saw... */
put_wk_in_table ( last_code, last_k,
string_table, &table_max);
already_entered = 1;
create_string(w, last_k);
w_code = last_k;
SHOW( { unsigned char *s; printf ( " w: '" ); )
SHOW( for (s = w; *s; s++)
printf( isprint(*s) ? "%c" : " %dd ", *s);)
SHOW( printf ( "'" ); } )
}
if ( in_buffer[in_counter] > table_max ) {
printf ( "\nInternal error #1\n" );
fclose ( infile );
fclose ( outfile );
exit ( 1 );
}
/* save for later */
last_code = in_buffer[in_counter];
ct = string_table[in_buffer[in_counter]].num;
k = last_k =
string_table[in_buffer[in_counter]].character;
if ( k == 0 ) {
output_char ( 0, out_buffer,
&out_counter, outfile);
update_table( 0, w, &w_code,
string_table, &table_max );
}
else {
w2[0] = '\0';
build_string ( w2, ct, string_table );
append_char ( w2, k );
j = strlen ( w2 );
last_k = *w2;
for ( i = 0; i < j; i++ ) {
output_char( w2[i], out_buffer,
&out_counter, outfile );
if ( !already_entered )
update_table ( w2[i], w, &w_code,
string_table, &table_max );
already_entered = 0;
}
}
}
/* get another block */
if ( feof ( infile ))
break;
codes_read = read_compressed_file ( in_buffer, infile );
in_counter = 0;
}
/* flush partial buffer */
if ( out_counter != 0 )
my_write ( outfile, out_buffer, 1, out_counter );
SHOW( print_string_table (string_table,
"DONE", BASE_TABLE+1, table_max ); )
#if defined(STATS)
printf ( "Table had %d entries at conclusion.\n",
table_max );
printf ( "Input file was %ld bytes.\n", ftell (infile ));
printf ( "Output file is %ld bytes.\n", ftell (outfile ));
#endif
}
/*-----------------------------------------------------------
* keep string_table updated
*---------------------------------------------------------*/
void update_table( int k, unsigned char *w, code_type *w_code,
table_item *string_table, unsigned *table_max)
{
code_type wk;
if ( k == '\0' || /* NULLs are special */
( wk = wk_is_in_table ( w, k, string_table )) == 0) {
if ( k != '\0' && strlen ( w ) != 0 )
put_wk_in_table ( *w_code, k,
string_table, table_max );
create_string ( w, k );
*w_code = k;
}
/* wk is a known code, so note what we've found */
else {
append_char ( w, k );
*w_code = wk;
}
SHOW( { unsigned char *s; printf ( " w: '" ); )
SHOW( for ( s = w; *s; s++ )
printf ( isprint ( *s ) ? "%c" : " %dd ", *s ); )
SHOW( printf ( "'" ); } )
}
/*-------------------------------------------------------
* read the type short from the compressed file.
*------------------------------------------------------*/
unsigned read_compressed_file ( code_type *inbuf, FILE *infile )
{
return my_read ( infile, inbuf,
sizeof ( code_type ), IB_LENGTH_D );
}
/*-------------------------------------------------------
* output the character k. It puts it in the output buffer.
* If the output buffer is full it writes the buffer to
* the output file.
*------------------------------------------------------*/
void output_char( int k, unsigned char *out_buffer,
unsigned *out_counter,
FILE *outfile )
{
if ( *out_counter >= OB_LENGTH_D ){
my_write ( outfile, out_buffer, 1, *out_counter );
*out_counter = 0;
}
SHOW( printf ( isprint ( k ) ? " Out: '%c'" :
" Out: '%dd'", k); )
out_buffer[*out_counter] = (unsigned char) k;
*out_counter += 1;
} /* ends output_character */